// 引入
var mongodb = require("mongodb");
// 实例化
let mongoCt = mongodb.MongoClient;
// 函数，把字符转换成objectId的对象性_id
let ObjectId = mongodb.ObjectId;
// 方便改库名
let sql = "app";
//连接库
let open = ({
	dbName = sql,
	collectionName,
	url = "mongodb://127.0.0.1:27017",
}) => {
	return new Promise((resolve, reject) => {
		// 实例化并连接
		mongoCt.connect(url, (err, client) => {
			// err错误 client链接后的客户端
			if (err) {
				reject(err);
			} else {
				// console.log(19,dbName)
				// 链接库和集合--let db=client.db('库名')--let user=db.collection('集合名')
				let db = client.db(dbName);
				// console.log(err)
				let collection = db.collection(collectionName);
				// console.log(err)
				resolve({ collection, client, ObjectId });
				//
				// console.log(27,'resolve运行了')
				// 丢给then
			}
		});
	});
};
// 查询库==》查询接口==》链接接口==》开库==》列表查询
let findList = ({
	collectionName, //集合名
	dbName = sql, //库名
	_page,
	_limit,
	_sort,
	q, //条件不能写死，条件会受次数q关键字查询的影响
	// 可选参数
	// 同样的概念，希望封装的接口是个promise
}) => {
	// 设定检索条件-->如果q查询某字段，就要去数据库里看含不含这字段
	// let rule = {};//{title:q}冲着title查动态的q-->q是全文检索，差的不是一个title,是数据里所有的键
	// 查包不包含-->正则--/q/--但是会把他当做一个字符串而不是一个变量，q没有传rule就是空对象，所以要赋值
	//======== let rule = q ? {title:new RegExp(q,g)} : {}//此函数可以接受字符串
	// eval('alert')往里放东西可以帮你把代码运行起来，可以放字符串
	let rule = q ? { auth: eval("/" + q + "/") } : {}; //字符串拼接用字符串把变量表达出来
	return new Promise((resolve, reject) => {
		// 开库--直接调用open
		open({
			// 不知道开哪个库开哪个集合，传哪个就开哪个
			dbName,
			collectionName,
			// 要用then看开库的结果
		})
			.then(
				// 会返回来一个集合和一个客户端
				({ collection, client }) => {
					// 在这里开始了一个真实的查询动作
					// 集合的查询：find，加个规则可有可无
					rule;
					collection
						.find(rule, {
							// 条件受q关键字检索影响，所以定义一个rule==>要的是一个对象
							// 此处的都是上面传下来的
							sort: { [_sort]: -1 },
							// 想把一个变量里面的内容动态化-->用方括号
							// ================举例================
							// var a
							// window.a 或window['a']也可以访问到这个变量a
							// var b = a        ---->  _sort就是b
							// 通过访问window[b]也可以访问到变量a   --->a就是给_sort赋值的动态数据--内容
							// 所以给_sort加方括号就实现了内容动态化
							skip: _page * _limit, //跳过的转换
							limit: _limit,
						})
						.toArray((err, result) => {
							// resolve/reject出去结果
							// 没有错误的情况下，result数组不为空[注意result是一个数组]
							// console.log(err,result)
							if (!err && result.length > 0) {
								// 查到数据了就丢出去
								resolve({
									err: 0,
									msg: "查询数据成功！！！",
									// 数据放在data里面result包装一下
									data: result,
								});
							} else {
								reject({
									// 可以放文案文档 或直接放优雅错误信息
									err: 1,
									msg: "查不到集合数据，集合请在39行promise里查错，集合名或find方法或64行toArray处排查",
								});
							}
							client.close();
						});
				}
				// 用来接收错误的额情况下的信息
				// 谁用findList就把错误信息抛给findList的使用方式
				// err自身也是一个promise
			)
			.catch(
				// 错误信息直接不动脑子用自己的resolve|resolve再丢出去
				(err) => {
					reject({
						err: 1,
						msg: "库连接失败，请检查39行promise里的部分",
					});
					client.close();
				}
			);
		// 列表查询动作
	});
};
// 查详情
let findDetail = ({
	dbName = sql,
	collectionName,
	// 还需要一个id，数据库里的id是不会重复的，如果没传设置一个默认值
	_id = null,
	// 然后接下来去吧必传参数设置一下，工具或者路由里面都可以
}) =>
	new Promise((resolve, reject) => {
		// 开库--查询(条件--id携带--格式)
		open({
			collectionName,
			dbName,
		}).then(({ collection, client }) => {
			// 查询 条件id
			// 判断id合法性
			if (_id && _id.length === 24) {
				collection
					.find(
						{
							_id: ObjectId(_id), //mongodb里的id格式
						},
						{ projection: { _id: 0 } }
					)
					.toArray((err, result) => {
						// 通过result和reject把结果抛出去
						if (!err && result.length > 0) {
							resolve({
								err: 0,
								msg: "成功",
								data: result[0],
								// 然后res.js里发生变化-->then
							});
						} else {
							reject({
								err: 1,
								msg: "msdb.js里121行开始查无数据",
							});
						}
						client.close();
					});
			} else {
				reject({
					err: 1,
					msg: "id有误",
				});
				client.close();
			}
		});
	});

// 删除信息
let deleteDetail = ({ dbName = sql, collectionName, _id = null }) =>
	new Promise((resolve, reject) => {
		open({
			collectionName,
			dbName,
		}).then(({ collection, client }) => {
			console.log(22222222);
			if (_id && _id.length === 24) {
				console.log(_id);
				collection.deleteOne({ _id: ObjectId(_id) },
					(err, result) => {
                        console.log(result)
						if (result.deletedCount) {
							console.log("删除成功");
							resolve({
								err: 0,
								msg: "删除成功",
							});
						} else {
							console.log("删除失败");
							reject({
								err: 1,
								msg: "删除失败",
							});
						}
						client.close();
					});
			} else {
				console.log("匹配失败");
				reject({
					err: 1,
					msg: "id有误/查无数据",
				});
				client.close();
			}
		});
	});

exports.open = open;
exports.findList = findList;
exports.findDetail = findDetail;
exports.deleteDetail = deleteDetail;
